package ixRedis

import (
	"errors"
	"sync"
	"time"
)

// Metrics 指标统计
type Metrics struct {
	// 连接相关
	TotalConnections  int64
	ActiveConnections int64
	FailedConnections int64

	// 操作相关
	TotalOperations      int64
	SuccessfulOperations int64
	FailedOperations     int64

	// 命令统计
	CommandCounts map[string]int64

	// 性能统计
	TotalLatency   time.Duration
	AverageLatency time.Duration
	MaxLatency     time.Duration
	MinLatency     time.Duration

	// 时间统计
	StartTime         time.Time
	LastOperationTime time.Time

	mu sync.RWMutex
}

// NewMetrics 创建指标统计
func NewMetrics() *Metrics {
	return &Metrics{
		CommandCounts: make(map[string]int64),
		StartTime:     time.Now(),
		MinLatency:    time.Hour, // 初始化为一个很大的值
	}
}

// RecordOperation 记录操作
func (m *Metrics) RecordOperation(command string, success bool, latency time.Duration) {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.TotalOperations++
	m.CommandCounts[command]++

	if success {
		m.SuccessfulOperations++
	} else {
		m.FailedOperations++
	}

	// 更新延迟统计
	m.TotalLatency += latency
	m.AverageLatency = m.TotalLatency / time.Duration(m.TotalOperations)

	if latency > m.MaxLatency {
		m.MaxLatency = latency
	}
	if latency < m.MinLatency {
		m.MinLatency = latency
	}

	m.LastOperationTime = time.Now()
}

// RecordConnection 记录连接
func (m *Metrics) RecordConnection(success bool) {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.TotalConnections++
	if success {
		m.ActiveConnections++
	} else {
		m.FailedConnections++
	}
}

// GetStats 获取统计信息
func (m *Metrics) GetStats() map[string]interface{} {
	m.mu.RLock()
	defer m.mu.RUnlock()

	uptime := time.Since(m.StartTime)
	successRate := float64(0)
	if m.TotalOperations > 0 {
		successRate = float64(m.SuccessfulOperations) / float64(m.TotalOperations) * 100
	}

	return map[string]interface{}{
		"uptime":                uptime.String(),
		"total_connections":     m.TotalConnections,
		"active_connections":    m.ActiveConnections,
		"failed_connections":    m.FailedConnections,
		"total_operations":      m.TotalOperations,
		"successful_operations": m.SuccessfulOperations,
		"failed_operations":     m.FailedOperations,
		"success_rate":          successRate,
		"average_latency":       m.AverageLatency.String(),
		"max_latency":           m.MaxLatency.String(),
		"min_latency":           m.MinLatency.String(),
		"command_counts":        m.CommandCounts,
		"last_operation_time":   m.LastOperationTime,
	}
}

// Reset 重置统计信息
func (m *Metrics) Reset() {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.TotalConnections = 0
	m.ActiveConnections = 0
	m.FailedConnections = 0
	m.TotalOperations = 0
	m.SuccessfulOperations = 0
	m.FailedOperations = 0
	m.CommandCounts = make(map[string]int64)
	m.TotalLatency = 0
	m.AverageLatency = 0
	m.MaxLatency = 0
	m.MinLatency = time.Hour
	m.StartTime = time.Now()
	m.LastOperationTime = time.Time{}
}

// MetricsClient 带指标的客户端
type MetricsClient struct {
	*Client
	metrics *Metrics
}

// NewMetricsClient 创建带指标的客户端
func (c *Client) NewMetricsClient() *MetricsClient {
	return &MetricsClient{
		Client:  c,
		metrics: NewMetrics(),
	}
}

// GetMetrics 获取指标
func (mc *MetricsClient) GetMetrics() *Metrics {
	return mc.metrics
}

// Set 设置键值（带指标）
func (mc *MetricsClient) Set(key string, value interface{}) error {
	start := time.Now()
	err := mc.Client.Set(key, value)
	latency := time.Since(start)

	mc.metrics.RecordOperation("SET", err == nil, latency)
	return err
}

// Get 获取键值（带指标）
func (mc *MetricsClient) Get(key string, dest interface{}) (bool, error) {
	start := time.Now()
	exists, err := mc.Client.Get(key, dest)
	latency := time.Since(start)

	mc.metrics.RecordOperation("GET", err == nil, latency)
	return exists, err
}

// Del 删除键（带指标）
func (mc *MetricsClient) Del(keys ...string) (int64, error) {
	start := time.Now()
	result, err := mc.Client.Del(keys...)
	latency := time.Since(start)

	mc.metrics.RecordOperation("DEL", err == nil, latency)
	return result, err
}

// Exists 检查键是否存在（带指标）
func (mc *MetricsClient) Exists(key string) (bool, error) {
	start := time.Now()
	result, err := mc.Client.Exists(key)
	latency := time.Since(start)

	mc.metrics.RecordOperation("EXISTS", err == nil, latency)
	return result, err
}

// HealthCheck 健康检查
type HealthCheck struct {
	client  *Client
	timeout time.Duration
}

// NewHealthCheck 创建健康检查
func (c *Client) NewHealthCheck(timeout time.Duration) *HealthCheck {
	return &HealthCheck{
		client:  c,
		timeout: timeout,
	}
}

// Check 执行健康检查
func (hc *HealthCheck) Check() error {
	conn, err := hc.client.getConn()
	if err != nil {
		return err
	}
	defer conn.Close()

	// 设置超时
	done := make(chan error, 1)
	go func() {
		_, err := conn.Do("PING")
		done <- err
	}()

	select {
	case err := <-done:
		return err
	case <-time.After(hc.timeout):
		return errors.New("health check timeout")
	}
}

// IsHealthy 检查是否健康
func (hc *HealthCheck) IsHealthy() bool {
	return hc.Check() == nil
}
